#include "HeadFile.h"
#include "DrawFunc.h"
#include <windows.h>

DrawFunc* DrawFunc::instance = nullptr;

DrawFunc * DrawFunc::Instance()
{
	if (instance == nullptr)
	{
		instance = new DrawFunc();
	}
	return instance;
}

DrawFunc * DrawFunc::Instance(SHORT s_w, SHORT s_h)
{
	if (instance == nullptr)
	{
		instance = new DrawFunc(s_w, s_h);
	}
	return instance;
}
//用于填充前画布缓存
DrawFunc::DrawFunc(SHORT s_w, SHORT s_h)
{
	screen_height = s_h;
	screen_width = s_w;
	h_out = GetStdHandle(STD_OUTPUT_HANDLE); //窗口句柄;
	buffer = CreateConsoleScreenBuffer(
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		CONSOLE_TEXTMODE_BUFFER,
		NULL
	);
//创建后台画布
	SetConsoleOutputCP(936);

	screen_width = s_w;
	screen_height = s_h;
	//Clean();

	size = { s_w, s_h };

	rc = { 0,0,size.X - 1,size.Y - 1 };
	SetConsoleWindowInfo(h_out, true, &rc);
	if (screen_width >= 100 || screen_height >= 100)
	{
		SetConsoleScreenBufferSize(buffer, size);
		SetConsoleScreenBufferSize(h_out, size);
	}
	else
	{
		SetConsoleScreenBufferSize(h_out, size);
		SetConsoleScreenBufferSize(buffer, size);
	}
	//设置后台画布的大小
	
	chiBuffer = new CHAR_INFO[screen_height * screen_width];//用于画布缓存
	
	coordBufSize.X = size.X;
	coordBufSize.Y = size.Y;

	coordBufCoord.X = 0;
	coordBufCoord.Y = 0;

	srctReadRect.Left = 0;
	srctReadRect.Right = size.X;
	srctReadRect.Top = 0;
	srctReadRect.Bottom = size.Y;

	srctWriteRect.Left = 0;
	srctWriteRect.Right = size.X;
	srctWriteRect.Top = 0;
	srctWriteRect.Bottom = size.Y;

}

DrawFunc::DrawFunc()
{
	screen_height = 60;
	screen_width = 150;
	h_out = GetStdHandle(STD_OUTPUT_HANDLE); //窗口句柄;
	buffer = CreateConsoleScreenBuffer(
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		CONSOLE_TEXTMODE_BUFFER,
		NULL
	);

	SetConsoleOutputCP(936);

	size = { screen_width, screen_height };

	rc = { 0,0,size.X - 1,size.Y - 1 };

	SetConsoleWindowInfo(h_out, true, &rc);

	if (screen_width >= 100 || screen_height >= 100)
	{
		SetConsoleScreenBufferSize(buffer, size);
		SetConsoleScreenBufferSize(h_out, size);
	}
	else
	{
		SetConsoleScreenBufferSize(h_out, size);
		SetConsoleScreenBufferSize(buffer, size);
	}

	chiBuffer = new CHAR_INFO[screen_width * screen_width];
	coordBufSize.X = size.X;
	coordBufSize.Y = size.Y;

	coordBufCoord.X = 0;
	coordBufCoord.Y = 0;

	srctReadRect.Left = 0;
	srctReadRect.Right = size.X;
	srctReadRect.Top = 0;
	srctReadRect.Bottom = size.Y;

	srctWriteRect.Left = 0;
	srctWriteRect.Right = size.X;
	srctWriteRect.Top = 0;
	srctWriteRect.Bottom = size.Y;
}


DrawFunc::~DrawFunc()
{
}

void DrawFunc::Clean()
{
	COORD home = { 0,0 };
	DWORD xx;
	FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_RED, screen_width * screen_height, home, &xx);
	FillConsoleOutputCharacter(buffer, ' ', screen_width * screen_height, home, &xx);
}

void DrawFunc::Draw(int x, int y, char* str)
{
	
	COORD pos = { x , y };
	DWORD xx;
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::Draw(int x, int y, int num)
{
	COORD pos = { x , y };
	DWORD xx;
	char str[20];
	_itoa_s(num, str, 20, 10);
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::Draw(int x, int y, double num)
{
	COORD pos = { x , y };
	DWORD xx;
	char str[10];
	sprintf_s(str, 10,"%f",num);
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::DrawWithWhite(int x, int y, char* str)
{
	COORD pos = { x , y };
	DWORD xx;
	FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::CN_Draw(int x, int y, char* str)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::CN_Draw(int x, int y, int num)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	char str[20];
	_itoa_s(num, str, 20, 10);
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::CN_Draw(int x, int y, double num)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	char str[10];
	sprintf_s(str, 10, "%f", num);
	WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
}

void DrawFunc::CN_Draw(int x, int y, char* str, int i)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	if(i == DRAWINBUFFER)
		WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
	else if(i == DRAWINHOUT)
		WriteConsoleOutputCharacter(h_out, str, strlen(str), pos, &xx);
}

void DrawFunc::CN_DrawWithWhite(int x, int y, char* str,int i)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	if (i == DRAWINBUFFER)
	{
		FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
	}
	else if (i == DRAWINHOUT)
	{
		FillConsoleOutputAttribute(h_out, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(h_out, str, strlen(str), pos, &xx);
	}
}

void DrawFunc::CN_DrawWithWhite(int x, int y, int num, int i)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	char str[20];
	_itoa_s(num, str, 20, 10);
	if (i == DRAWINBUFFER)
	{
		FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
	}
	else if (i == DRAWINHOUT)
	{
		FillConsoleOutputAttribute(h_out, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(h_out, str, strlen(str), pos, &xx);
	}
}

void DrawFunc::CN_DrawWithGreen(int x, int y, char* str, int i)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	if (i == DRAWINBUFFER)
	{
		FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
	}
	else if (i == DRAWINHOUT)
	{
		FillConsoleOutputAttribute(h_out, FOREGROUND_INTENSITY | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(h_out, str, strlen(str), pos, &xx);
	}
}

void DrawFunc::CN_DrawWithGreen(int x, int y, int num, int i)
{
	COORD pos = { x*2 , y };
	DWORD xx;
	char str[20];
	_itoa_s(num, str, 20, 10);
	if (i == DRAWINBUFFER)
	{
		FillConsoleOutputAttribute(buffer, FOREGROUND_INTENSITY | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(buffer, str, strlen(str), pos, &xx);
	}
	else if (i == DRAWINHOUT)
	{
		FillConsoleOutputAttribute(h_out, FOREGROUND_INTENSITY | FOREGROUND_GREEN, strlen(str) * 2, pos, &xx);
		WriteConsoleOutputCharacter(h_out, str, strlen(str), pos, &xx);
	}
}

void DrawFunc::Flush()
{
	if (chiBuffer == NULL)
		return;
	//读取后台画布上的所有象素
	ReadConsoleOutput(
		buffer,		// screen to read from 
		chiBuffer,      // buffer to copy into 
		coordBufSize,   // col-row size of chiBuffer 
		coordBufCoord,  // top left dest. cell in chiBuffer 
		&srctReadRect);


	//把这些象素拷贝到前台画布
	WriteConsoleOutput(
		h_out,  // screen buffer to write to 
		chiBuffer,        // buffer to copy from 
		coordBufSize,     // col-row size of chiBuffer 
		coordBufCoord,    // top left src cell in chiBuffer 
		&srctWriteRect);
}